<template>
  <div class="app-container">
    <el-row :gutter="15">
      <el-col :span="8">
        <el-card class="box-card">
          <template #header>
            <div class="card-header">
              <span>菜单目录</span>
              <el-button
                style="float: right; padding: 3px 0"
                link
                type="primary"
                @click="
                  handleOpenDialog({
                    menuTitle: '根目录',
                  })
                "
              >
                添加菜单
              </el-button>
            </div>
          </template>
          <div>
            <el-tree
              :data="menuTree"
              node-key="id"
              default-expand-all
              :expand-on-click-node="false"
              v-loading="loading"
            >
              <template #default="{ node, data }">
                <span class="custom-tree-node" @click="openMenus(data.id)">
                  <span class="custom-tree-node-title">
                    {{ node.data.label }}
                  </span>
                  <span>
                    <el-button
                      type="primary"
                      link
                      @click.stop="appendMenu(node, data)"
                    >
                      <el-icon><Plus /></el-icon>
                    </el-button>
                    <el-button
                      type="primary"
                      link
                      @click.stop="handleOpenDialog(data)"
                    >
                      <el-icon><Edit /></el-icon>
                    </el-button>
                    <el-button
                      type="danger"
                      link
                      @click.stop="removeMenu(node, data)"
                    >
                      <el-icon><DeleteFilled /></el-icon>
                    </el-button>
                  </span>
                </span>
              </template>
            </el-tree>
          </div>
        </el-card>
      </el-col>
      <el-col :span="16">
        <el-card class="box-card">
          <template #header>
            <div class="card-header">
              <span>菜单按钮列表</span>
              <el-button
                v-if="menuId !== undefined"
                style="float: right; padding: 3px 0"
                link
                type="primary"
                @click="handleMenuButton()"
              >
                添加按钮
              </el-button>
            </div>
          </template>
          <div>
            <el-table
              :data="buttonList"
              border
              style="width: 100%"
              v-loading="tableLoading"
            >
              <el-table-column
                fixed
                prop="buttonTitle"
                align="center"
                label="按钮标题"
                width="150"
              />
              <el-table-column
                prop="buttonCode"
                align="center"
                label="按钮编码"
              />
              <el-table-column prop="url" align="center" label="请求地址" />
              <el-table-column prop="method" align="center" label="请求方式" />
              <el-table-column
                fixed="right"
                align="center"
                label="操作"
                width="150"
              >
                <template #default="scope">
                  <el-button
                    type="primary"
                    link
                    @click="handleMenuButton(scope.row)"
                  >
                    编辑
                  </el-button>
                  <el-button
                    type="danger"
                    link
                    @click="handleDelete(scope.row)"
                  >
                    删除
                  </el-button>
                </template>
              </el-table-column>
            </el-table>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 菜单修改 -->
    <EditMenuDetailsDialog
      v-if="dialogVisible"
      :menuId="menuId"
      :parentMenu="parentMenu"
      :closedDialog="handleClosedDialog"
    />
    <!-- 菜单按钮 新增/修改 -->
    <EditMenuButtonDetailsDialog
      v-if="buttonDialogVisible"
      :menuButtonId="menuButtonId"
      :menuId="menuId"
      :closedDialog="handleMenuButtonClosedDialog"
    />
  </div>
</template>

<script lang="ts" setup>
import { ref, onBeforeMount } from "vue";
import MenuAPI, { type MenuVO } from "@/api/system/sys/menu";
import MenuButtonAPI, { type MenuButtonVO } from "@/api/system/sys/menuButton";
import { ElMessageBox } from "element-plus";
import type Node from "element-plus/es/components/tree/src/model/node";
import EditMenuDetailsDialog from "@/views/system/sys/menu/components/EditMenuDetailsDialog.vue";
import EditMenuButtonDetailsDialog from "@/views/system/sys/menu/components/EditMenuButtonDetailsDialog.vue";

/** 菜单管理 */
defineOptions({
  name: "SysMenu",
});
/** 父级菜单 */
const parentMenu = ref<MenuVO>();
/** 菜单弹窗状态 */
const dialogVisible = ref<boolean>(false);
/** 菜单按钮弹窗状态 */
const buttonDialogVisible = ref<boolean>(false);
/** 菜单状态 */
const loading = ref<boolean>(false);
/** 按钮状态 */
const tableLoading = ref<boolean>(false);
/** 菜单树 */
const menuTree = ref<MenuVO[]>([]);
/** 表格数据 */
const buttonList = ref<any[]>([]);
/** 菜单id */
const menuId = ref<string>("");
/** 菜单按钮id */
const menuButtonId = ref<number>();

/** 菜单树接口 */
const getTableData = () => {
  loading.value = true;
  // 初始化菜单树
  MenuAPI.getMenuTreesApi()
    .then((res) => {
      const { status, data } = res;
      if (res && status === 200) {
        menuTree.value = data;
      }
    })
    .finally(() => {
      loading.value = false;
    });
};

/** 打开弹窗 */
const handleOpenDialog = (data: MenuVO) => {
  dialogVisible.value = true;
  // 当前节点id
  menuId.value = data.id!;
  // 当前节点,当作父级id
  parentMenu.value = data;
};
/** 关闭弹窗 */
const handleClosedDialog = (data: any) => {
  // 有值，则刷新列表
  if (data) {
    getTableData();
  }
  dialogVisible.value = false;
};
/** 随机生成3位数 */
const generateThreeDigitNumber = () => {
  return Math.floor(Math.random() * (999 - 100 + 1)) + 100;
};
/** 添加子菜单节点 */
const appendMenu = (node: Node, data: MenuVO) => {
  // 初始化子菜单
  let menuForm: any = {};
  menuForm.parentId = data.id;
  menuForm.menuTitle = "子菜单";
  menuForm.menuCode = data.menuCode + "_" + generateThreeDigitNumber();
  MenuAPI.addSysMenuApi(menuForm).then((res) => {
    const { status, data } = res;
    if (status === 200) {
      // 动态新生成新的节点则
      const newNode = data;
      newNode.children = [];
      newNode.label = data.menuTitle;
      // 动态添加新节点
      node.data.children.push(newNode);
      ElMessage.success("子菜单添加成功");
    }
  });
};
/** 删除菜单节点 */
const removeMenu = (node: Node, data: MenuVO) => {
  ElMessageBox.confirm(`正在删除：${data.menuTitle}，确认删除？`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    // 判断当前节点是否存在子节点
    if (data.children && data.children.length === 0) {
      data.id &&
        MenuAPI.delSysMenuApi(data.id).then((res) => {
          if (res && res.status === 200) {
            // 动态删除当前节点
            const parent = node.parent;
            const children = parent.data.children || parent.data;
            // 获取当前节点index
            const index = children.findIndex((d: MenuVO) => d.id === data.id);
            // 删除指定节点
            children.splice(index, 1);
            ElMessage.success("删除成功");
          }
        });
    } else {
      ElMessage.error("请删除当前菜单的所有子菜单");
    }
  });
};

/** 打开添加菜单按钮弹窗 */
const handleMenuButton = (row?: MenuButtonVO) => {
  if (row?.id) {
    menuButtonId.value = row.id;
  }
  buttonDialogVisible.value = true;
};
/** 关闭弹窗 */
const handleMenuButtonClosedDialog = (menuId: string) => {
  // 有值，则刷新列表
  if (menuId) {
    getButtonsByMenuId(menuId);
  }
  menuButtonId.value = undefined;
  buttonDialogVisible.value = false;
};
/** 获取菜单按钮列表 */
const getButtonsByMenuId = (id: string) => {
  tableLoading.value = true;
  MenuButtonAPI.getSysMenuButtonListApi({ menuId: id })
    .then((res) => {
      if (res && res.status === 200) {
        buttonList.value = res.data.rows;
      }
    })
    .finally(() => {
      tableLoading.value = false;
    });
};

/** 删除菜单按钮 */
const handleDelete = (row: MenuButtonVO) => {
  ElMessageBox.confirm(`正在删除：${row.buttonTitle}，确认删除？`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    row.id &&
      MenuButtonAPI.delSysMenuButtonApi(row.id).then((res) => {
        const { status, message } = res;
        if (status === 200) {
          getButtonsByMenuId(menuId.value);
          ElMessage.success("删除成功");
        } else {
          ElMessage.error(message);
        }
      });
  });
};
/** 点击菜单 */
const openMenus = (id: string) => {
  menuId.value = id;
  getButtonsByMenuId(id);
};

/** 页面渲染完成后初始化 */
onBeforeMount(async () => {
  getTableData();
});
</script>

<style lang="scss" scoped>
.search-wrapper {
  margin-bottom: 20px;

  :deep(.el-card__body) {
    padding-bottom: 2px;
  }
}

.toolbar-wrapper {
  display: flex;
  justify-content: space-between;
  margin-bottom: 20px;
}

.table-wrapper {
  margin-bottom: 20px;
}

.pager-wrapper {
  display: flex;
  justify-content: flex-end;
}
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}
</style>
